import events from 'events';
import socketIO, { Socket } from 'socket.io';
// import { llog, lerror } from './util/logger';
import { Agent } from './models/Agent';

import { net as netAPI } from './protocolConst.json';
import { Client, ActionArgs } from './client';
import { llog } from './util/logger';

export const bindSocketIO = function(server) {
	let io = socketIO(server, {
		pingTimeout: 10 * 1000,
		pingInterval: 10 * 1000,
	});

	io.on('connection', function(socket) {
		Client.createClient(socket);
	});
};

Client.actionEmitter.on(netAPI.getAllAgents, (client: Client, action) => {
	let { id } = action.payload;
	let agents = Array.from(Agent.getAllAgents().values());
	client.sendAction({
		seq: action.seq,
		payload: agents.map((v, k) => v.desc),
	});
});

Client.actionEmitter.on(netAPI.getAgent, async (client: Client, action) => {
	let { id, options, userdata } = action.payload;
	let agent = await Agent.getAgent(id);
	if (!agent) {
		client.sendAction({ seq: action.seq, id, err: 'not exist' });
	} else {
		client.sendAction({ seq: action.seq, payload: agent.desc });
	}
});

Client.actionEmitter.on(netAPI.requestLogin, async (client: Client, action) => {
	let { id, options, userdata } = action.payload;
	let agent = await Agent.findOrCreateAgent(id, options);
	if (!agent) {
		client.sendAction({ seq: action.seq, err: 'not available' });
		return;
	}
	client.subscribeAgent(agent, userdata);
	agent.start();
});

Client.actionEmitter.on(netAPI.release, (client: Client, action) => {
	let { id } = action.payload;
	let agent = Agent.getAgent(id);
	if (!agent) {
		client.sendAction({ seq: action.seq, err: 'not exist' });
		return;
	}
	Agent.deleteAgent(id);
	client.sendAction({ seq: action.seq, payload: {} });
});

Client.actionEmitter.on(netAPI.getContacts, async (client: Client, action) => {
	let agent = Agent.getAgent(action.payload.id);
	if (agent && agent.wxid) {
		let contacts = await agent.getContacts();
		client.sendAction({ seq: action.seq, payload: contacts });
	} else {
		client.sendAction({ seq: action.seq, err: 'agent not login' });
	}
});

Client.actionEmitter.on(netAPI.getRooms, async (client: Client, action) => {
	let agent = Agent.getAgent(action.payload.id);
	if (agent && agent.wxid) {
		let contacts = await agent.getRooms();
		client.sendAction({ seq: action.seq, payload: contacts });
	} else {
		client.sendAction({ seq: action.seq, err: 'agent not login' });
	}
});

Client.actionEmitter.on(netAPI.sendMessage, async (client: Client, action) => {
	let { id, contactId, text } = action.payload;
	let agent = Agent.getAgent(id);
	if (agent && agent.wxid) {
		agent.sendMessage(contactId, text);
		client.sendAction({ seq: action.seq, payload: {} });
	} else {
		client.sendAction({ seq: action.seq, err: 'agent not login' });
	}
});

Client.actionEmitter.on(netAPI.sendControlCommand, async (client: Client, action) => {
	let { id, cmd } = action.payload;
	let agent = Agent.getAgent(id);
	if (agent) {
		let result = agent.processCommand(cmd);
		client.sendAction({ seq: action.seq, payload: result });
	} else {
		client.sendAction({ seq: action.seq, err: 'agent not exist' });
	}
});

process.on('unhandledRejection', function(reason, p) {
	console.log('Possibly Unhandled Rejection at: Promise ', ' reason: ', reason);
	// application specific logging here
});
